package org.datamining.apriori.custom;

import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;


import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;
import weka.filters.Filter;

/**
 * @author Betul Coskuner (coskunerbetul@gmail.com)
 * @since 18th May 2014
 * 
 * Dosya yoluna gore DataSet dolduran, form elemanlarini algoritma ile baglayan, 
 * algoritmayi parametreleri alarak calistiran ve formda goruntuleyen metotlara sahip bir siniftir
 * Apriori algoritmasini gorsel arayuz ile bagdastiran yardimci siniftir. 
 *
 */
public class AprioriManager {

	private static Instances veriSeti;
	private static Thread m_IOThread;
	private static AttributeSelectionPanel pnlAttributeSelection;
	private static JButton btnRemove;
	
	public static Instances getInstances()
	{
		return veriSeti;
	}
	
	public static void ElemanlariBagla(AttributeSelectionPanel pnlAttrSel, JButton p_btnRemove)
	{
		pnlAttributeSelection = pnlAttrSel;
		btnRemove = p_btnRemove;
	}
	
	//Yerel veri setini doldurur
	//runApriori metodu calistirilmadan evvel bu metot calisitirilip "veriSeti" degiskeninin doldurulmasi gerekir
	public static void veriSetiHazirla(String filePath)
	{
		DataSource veriKaynagi;
		
		try {
			veriKaynagi = new DataSource(filePath);
			veriSeti = veriKaynagi.getDataSet();
			
			if (veriSeti.classIndex() == -1)
				veriSeti.setClassIndex(veriSeti.numAttributes() - 1);
			
			if(pnlAttributeSelection!=null)
				pnlAttributeSelection.setInstances(veriSeti);
			
		} catch (Exception e) {

			e.printStackTrace();
		}
	}
	
	//Apriori calistirmak icin gereken tum parametreler ayri bir sinifta toplandi
	public static class AprioriArgs
	{
		public String filePath; //ARFF dosyasinin yolu
		public JTextArea output; //Sonuclarin aktarilacagi JTextArea
		public int numberOfRules; // Kural Sayisi
		public double deltaValue; //Delte degeri
		public double minConfidence; // Minimum Guven
		public double minSupport; // Minimum Destek
	}

public static void simdiCalistir(AprioriArgs a) {
	 
		
		// Weka'da Association sekmesinde Apriori algoritmasi seciliyken
		// kopyalanan parametre listesidir
		String[] parametreler = { 	"-N", String.valueOf(a.numberOfRules) , 
									"-T", "0", 
									"-C", String.valueOf(a.minConfidence), 
									"-D", String.valueOf(a.deltaValue),
									"-U", "1.0", 
									"-M", String.valueOf(a.minSupport), 
									"-S", "-1.0", 
									"-c", "-1" };

		try {

			if(veriSeti==null)
				throw new Exception("Veri Seti bo� iken Apriori �al��t�r�lamaz. �nce veriSetiHazirla(String dosyaYolu) metodunu kullan�n");

			// Bir Apriori nesnesi oluuturduk
			Apriori ap = new Apriori();

			// Ayar parametrelerini uyguluyoruz
			ap.setOptions(parametreler);

			// iliskisel kurallari tespit eden algoritmayi "veriSeti" kaynak
			// kullanarak calistirdik
			ap.buildAssociations(veriSeti);

			// Apriori nesnesinden kurallari string'e donusturrmesini istedik.
			String kurallar = ap.toString();

			// Kurallari konsolda gosterdik
			//System.out.println("Kurallar: " + kurallar);
			// Kurallari textArea elemaninda goster
			a.output.setText(kurallar);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	//Remove filresinin uygulanmasinda kullanildi
	// NOT: Weka'dan uyarlandi
	public static void applyFilter(final Filter filter) {

		if (m_IOThread == null) {
			m_IOThread = new Thread() {
				@Override
				public void run() {
					try {
						Instances copy = new Instances(veriSeti);
						// Classindex'i numAttributes-1 olarak aldik eski hali
						// "classIndex" idi
						// copy.setClassIndex(classIndex);
						copy.setClassIndex(veriSeti.numAttributes() - 1);
						Filter filterCopy = Filter.makeCopy(filter);
						filterCopy.setInputFormat(copy);
						Instances newInstances = Filter.useFilter(copy,
								filterCopy);
						if (newInstances == null
								|| newInstances.numAttributes() < 1) {
							throw new Exception("Dataset is empty.");
						}

						if (veriSeti.classIndex() < 0)
							newInstances.setClassIndex(-1);
						veriSeti = newInstances;
						setInstances(veriSeti);

					} catch (Exception ex) {
						// TODO: filtrelemede hata mesaji verdirilecek
					}
					m_IOThread = null;
				}
			};
			m_IOThread.setPriority(Thread.MIN_PRIORITY); // UI has most priority
			m_IOThread.start();
		} else {
			JOptionPane.showMessageDialog(null,
					"Can't apply filter at this time,\n"
							+ "currently busy with other IO", "Apply Filter",
					JOptionPane.WARNING_MESSAGE);
		}
	}
	
	//Paneldeki Attribute secimi instance'lara uygulanir
	// NOT: Weka'dan uyarlandi
	public static void setInstances(Instances inst) {

		veriSeti = inst;
		try {
			Runnable r = new Runnable() {
				public void run() {
					boolean first = (pnlAttributeSelection.getTableModel() == null);

					// m_InstSummaryPanel.setInstances(veriSeti);
					pnlAttributeSelection.setInstances(veriSeti);

					if (first) {
						TableModel model = pnlAttributeSelection.getTableModel();
						model.addTableModelListener(new TableModelListener() {
							public void tableChanged(TableModelEvent e) {
								if (pnlAttributeSelection
										.getSelectedAttributes() != null
										&& pnlAttributeSelection
												.getSelectedAttributes().length > 0) {
									btnRemove.setEnabled(true);
								} else {
									btnRemove.setEnabled(false);
								}
							}
						});
					}
					btnRemove.setEnabled(true);
					// select the first attribute in the list
					pnlAttributeSelection.getSelectionModel()
							.setSelectionInterval(0, 0);
				}
			};
			if (SwingUtilities.isEventDispatchThread()) {
				r.run();
			} else {
				SwingUtilities.invokeAndWait(r);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

}

